﻿using LotteryCrawler.Core;
using SuperFx;
using SuperLottery.Datas;
using SuperLottery.Datas.DbModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Globalization;

namespace LotteryCrawler.Visual
{
	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();
		}

		private void btnTest_Click(object sender, EventArgs e)
		{
			Crawler crawler = new Crawler();
			var data = crawler.CrawlShuangSeQiuFrom500("2014031");
		}

		private void btnStart_Click(object sender, EventArgs e)
		{
			Button btn = (Button)sender;
			if (btn.Text == "Start")
			{
				btn.Text = "Stop";
				this.btnNextShuangSeQiu.Enabled = false;
				this.btnNextQiLeCai.Enabled = false;
				this.btnNextDaLeTou.Enabled = false;
				this.btnTest.Enabled = false;

				this.timerCrawler.Start();
			}
			else
			{
				btn.Text = "Start";
				this.btnNextShuangSeQiu.Enabled = true;
				this.btnNextQiLeCai.Enabled = true;
				this.btnNextDaLeTou.Enabled = true;
				this.btnTest.Enabled = true;

				this.timerCrawler.Stop();
			}
		}

		private void BackRun()
		{
			DayOfWeek dayOfWeek = DateTime.Now.DayOfWeek;
			TimeSpan time = DateTime.Now.TimeOfDay;

			// 双色球，其开奖日为每周二、四、日.
			if (DayOfWeek.Tuesday == dayOfWeek || DayOfWeek.Thursday == dayOfWeek || DayOfWeek.Sunday == dayOfWeek)
			{// 2, 4, 7
				this.OutputToLogBox("今天[福彩-双色球]开奖");
				// 双色球的开奖时间为21点30分.
				TimeSpan bTime = TimeSpan.Parse("21:30:00");
				if (time >= bTime)
				{// 超过21:30
					this.CrawlShuangSeQiu();
				}
			}

			// 七乐彩，其开奖日为每周一、三、五.
			if (DayOfWeek.Monday == dayOfWeek || DayOfWeek.Wednesday == dayOfWeek || DayOfWeek.Friday == dayOfWeek)
			{// 1, 3, 5
				this.OutputToLogBox("今天[福彩-七乐彩]开奖");
				// 七乐彩的开奖时间为21点30分.
				TimeSpan bTime = TimeSpan.Parse("21:30:00");
				if (time >= bTime)
				{// 超过21:30
					this.CrawlQiLeCai();
				}
			}

			// 大乐透，其开奖日为每周一、三、六.
			if (DayOfWeek.Monday == dayOfWeek || DayOfWeek.Wednesday == dayOfWeek || DayOfWeek.Saturday == dayOfWeek)
			{// 1, 3, 6
				this.OutputToLogBox("今天[体彩-大乐透]开奖");
				// 大乐透的开奖时间为20点30分.
				TimeSpan bTime = TimeSpan.Parse("20:30:00");
				if (time >= bTime)
				{// 超过20:30
					this.CrawlDaLeTou();
				}
			}
		}

		/// <summary>
		/// 获取下一次彩票开奖期号.
		/// </summary>
		/// <param name="issuer">发行方.</param>
		/// <param name="game">彩种.</param>
		/// <returns></returns>
		private string GetNextIssueNumber(string issuer, string game)
		{
			var latest = LotteryDrawDbService.Instance.GetLatestLotteryDraw(issuer, game);

			if (latest != null)
			{
				// 如果最新记录的开奖日期是今天，则直接返回今天开奖期号.
				if (latest.DrawDate == DateTime.Today)
				{
					return latest.IssueNumber;
				}

				// 如果是新的一年开始，则需要升级开奖期号的年份
				if (latest.DrawDate.Year < DateTime.Today.Year)
				{
					if (issuer == "福彩")
					{
						return (latest.DrawDate.Year + 1).ToString() + "001";
					}
					else if (issuer == "体彩")
					{
						return (latest.DrawDate.Year + 1).ToString().Substring(2,2) + "001";
					}
					else
					{
						return "";
					}
				}

				// 开奖期号+1
				return (Int32.Parse(latest.IssueNumber) + 1).ToString();
			}
			else
			{
				if (issuer == "福彩")
				{
					return "2013001";
				}
				else if (issuer == "体彩")
				{
					return "13001";
				}
				else
				{
					return "";
				}
			}
		}

		private void btnNextShuangSeQiu_Click(object sender, EventArgs e)
		{
			this.CrawlShuangSeQiu();
		}

		private void btnNextQiLeCai_Click(object sender, EventArgs e)
		{
			this.CrawlQiLeCai();
		}

		private void btnNextDaLeTou_Click(object sender, EventArgs e)
		{
			this.CrawlDaLeTou();
		}

		private void CrawlShuangSeQiu()
		{
			string issueNumber = this.GetNextIssueNumber("福彩", "双色球");
			try
			{
				Crawler crawler = new Crawler();
				var result = crawler.CrawlShuangSeQiuFrom500(issueNumber);
				this.SaveDrawResult(result);
				this.OutputToLogBox(result);
			}
			catch (Exception ex)
			{
				if (ex.Message == "未抓取到数据")
				{
					this.OutputToLogBox(String.Format("双色球 第{0}期 未抓取到数据", issueNumber));
				}
				else
				{
					this.OutputToLogBox(ex);
				}
			}
		}

		private void CrawlQiLeCai()
		{
			string issueNumber = this.GetNextIssueNumber("福彩", "七乐彩");
			try
			{
				Crawler crawler = new Crawler();
				var result = crawler.CrawlQiLeCaiFrom500(issueNumber);
				this.SaveDrawResult(result);
				this.OutputToLogBox(result);
			}
			catch (Exception ex)
			{
				if (ex.Message == "未抓取到数据")
				{
					this.OutputToLogBox(String.Format("双色球 第{0}期 未抓取到数据", issueNumber));
				}
				else
				{
					this.OutputToLogBox(ex);
				}
			}
		}

		private void CrawlDaLeTou()
		{
			string issueNumber = this.GetNextIssueNumber("体彩", "大乐透");
			try
			{
				Crawler crawler = new Crawler();
				var result = crawler.CrawlDaLeTouFrom500(issueNumber);
				this.SaveDrawResult(result);
				this.OutputToLogBox(result);
			}
			catch (Exception ex)
			{
				if (ex.Message == "未抓取到数据")
				{
					this.OutputToLogBox(String.Format("大乐透 第{0}期 未抓取到数据", issueNumber));
				}
				else
				{
					this.OutputToLogBox(ex);
				}
			}
		}

		private void SaveDrawResult(DrawResult result)
		{
			LotteryDraw draw = result.Draw;
			LotteryDraw oldDraw = LotteryDrawDbService.Instance.GetLotteryDraw(draw.Issuer, draw.Game, draw.IssueNumber);
			if (oldDraw != null)
			{// 已经存在
				ObjectConverter.SetObjectValue(draw, oldDraw, "Id", "AddTime", "UpdateTime");
				draw = LotteryDrawDbService.Instance.Update(oldDraw);

				LotteryDrawDbService.Instance.Update(result.Details, oldDraw.Id);
			}
			else
			{
				LotteryDrawDbService.Instance.Create(result.Draw);
				LotteryDrawDbService.Instance.Create(result.Details, draw.Id);
			}
			var latest = LotteryDrawDbService.Instance.GetLatestLotteryDraw(draw.Issuer, draw.Game);
			if (latest == null || draw.DrawDate >= latest.DrawDate)
			{
				LotteryDrawDbService.Instance.SaveToLatest(draw);
			}
		}

		public delegate void OutputLog();

		private void OutputToLogBox(Exception ex)
		{
			string message = this.GetExceptionFullMessage(ex);

			if (!logBox.InvokeRequired)
			{
				this.AppendToErrorLogBox(message);
			}
			else
			{
				this.Invoke(new OutputLog(() => { this.AppendToErrorLogBox(message); }));
			}
		}

		private void OutputToLogBox(string message)
		{
			message = DateTime.Now + Environment.NewLine + message + Environment.NewLine;

			if (!normalLogBox.InvokeRequired)
			{
				this.AppendToNormalLogBox(message);
			}
			else
			{
				this.Invoke(new OutputLog(() => { this.AppendToNormalLogBox(message); }));
			}
		}

		private void OutputToLogBox(DrawResult result)
		{
			string tMessage = "{0}\r\n[{1}{2}],[{3}期],[{4}],[{5}],[{6}]\r\n";

			string message = String.Format(tMessage, DateTime.Now, result.Draw.Issuer, result.Draw.Game, result.Draw.IssueNumber, result.Draw.DrawDate.ToString("yyyy/MM/dd"), result.Draw.Numbers, result.Draw.BonusNumbers);

			if (!normalLogBox.InvokeRequired)
			{
				this.AppendToNormalLogBox(message);
			}
			else
			{
				this.Invoke(new OutputLog(() => { this.AppendToNormalLogBox(message); }));
			}
		}

		private void AppendToErrorLogBox(string message)
		{
			if (logBox.Lines.Length > 1000)
			{
				logBox.Clear();
			}

			logBox.AppendText(message);
		}

		private void AppendToNormalLogBox(string message)
		{
			if (normalLogBox.Lines.Length > 1000)
			{
				normalLogBox.Clear();
			}

			normalLogBox.AppendText(message);
		}

		private string GetExceptionFullMessage(Exception ex)
		{
			string message = DateTime.Now + Environment.NewLine
				+ ex.Message + Environment.NewLine
				+ ex.Source + Environment.NewLine
				+ ex.StackTrace + Environment.NewLine;

			if (ex.InnerException != null)
			{
				message += ex.Message + Environment.NewLine
					+ ex.Source + Environment.NewLine
					+ ex.StackTrace + Environment.NewLine;
			}

			return message;
		}

		private bool isRunning = false;
		private void timerCrawler_Tick(object sender, EventArgs e)
		{
			if (isRunning == true)
			{
				this.OutputToLogBox("上一次尚未执行完");
			}
			try
			{
				isRunning = true;
				this.BackRun();
			}
			finally
			{
				isRunning = false;
			}

			if (DateTime.Now.TimeOfDay < TimeSpan.Parse("20:30:00"))
			{
				this.OutputToLogBox("当前5分钟刷新一次");
				timerCrawler.Interval = 5 * 60 * 1000;
			}
			else
			{
				this.OutputToLogBox("当前半分钟刷新一次");
				timerCrawler.Interval = 30 * 1000;
			}
		}
	}
}
